package com.galaxy.service.realm;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.galaxy.commom.base.exception.RequestException;
import com.galaxy.commom.base.jwt.JwtToken;
import com.galaxy.commom.base.utils.Collections3;
import com.galaxy.commom.base.utils.JwtUtil;
import com.galaxy.service.entity.system.User;
import com.galaxy.service.service.system.UserService;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 自定义权限域
 * @author caijinbang
 * @date 2018/10/28 01:12
 */
@Slf4j
public class MyRealm extends AuthorizingRealm {

  @Autowired
  private UserService userService;

  @Autowired
  private CacheManager cacheManager;

  @Override
  public boolean supports(AuthenticationToken token) {
    return token instanceof JwtToken;
  }

  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    log.info("Shiro权限验证执行");
    JwtToken jwtToken = new JwtToken();
    BeanUtils.copyProperties(principalCollection.getPrimaryPrincipal(),jwtToken);
    if(jwtToken.getUsername()!=null){
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      User findUser = userService.findUserByName(jwtToken.getUsername(),true);
      if(findUser!=null){
        if(findUser.getRoles()!=null){
          findUser.getRoles().forEach(role->{
            info.addRole(role.getName());
            if(Collections3.isNotEmpty(role.getPermissions())){
              role.getPermissions().forEach(v->{
                if(!"".equals(v.getPermission().trim())){
                  info.addStringPermission(v.getPermission());
                }
              });
            }
          });
        }
        return info;
      }
    }
    throw new DisabledAccountException("用户信息异常，请重新登录！");
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    JwtToken token  = (JwtToken) authenticationToken;
    User user= new User();
    String username = token.getUsername()!=null ? token.getUsername() : JwtUtil.getUsername(token.getToken());
    try {
      user = userService.selectOne(new EntityWrapper<User>()
          .eq("username",username)
          .setSqlSelect("id,username,status,password"));
    }catch (RequestException e){
      throw new DisabledAccountException(e.getMsg());
    }
    if(user==null){
      throw new DisabledAccountException("用户不存在！");
    }
    if(user.getStatus()!=1){
      throw new DisabledAccountException("用户账户已锁定，暂无法登陆！");
    }

    if(token.getUsername()==null){
      token.setUsername(user.getUserName());
    }

    String sign = JwtUtil.sign(user.getId(), user.getUserName(), user.getPassword());
    if(token.getToken()==null) {
      token.setToken(sign);
    }
    token.setUid(user.getId());
    return new SimpleAuthenticationInfo(token,user.getPassword(),user.getId());
  }

  public void clearAuthByUserId(String uid,Boolean author, Boolean out){
    //获取所有session
    Cache<Object, Object> cache = cacheManager
        .getCache(MyRealm.class.getName()+".authorizationCache");
    cache.remove(uid);
  }

  public void clearAuthByUserIdCollection(List<String> userList,Boolean author, Boolean out){
    Cache<Object, Object> cache = cacheManager
        .getCache(MyRealm.class.getName()+".authorizationCache");
    userList.forEach(cache::remove);
  }
}
